package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.alibaba.fastjson.JSON;
import com.zzyl.dto.LoginDto;
import com.zzyl.entity.User;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.ResourceMapper;
import com.zzyl.mapper.UserMapper;
import com.zzyl.properties.JwtTokenProperties;
import com.zzyl.service.LoginService;
import com.zzyl.utils.JwtUtil;
import com.zzyl.vo.LoginVo;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@RequiredArgsConstructor
public class LoginServiceImpl implements LoginService {

    @Autowired
    private JwtTokenProperties jwtTokenProperties;

    @Autowired
    private UserMapper userMapper;

    final ResourceMapper resourceMapper;
    final StringRedisTemplate stringRedisTemplate;

    /**
     * 后台用户登录
     *
     * @param dto
     */
    @Override
    public LoginVo login(LoginDto dto) {
//        1.先根据用户名查用户
        User user = userMapper.selectByUsername(dto.getUsername());
        if (ObjectUtil.isEmpty(user)) {
            // 未找到该用户
            throw new BaseException(BasicEnum.INCORRECT_PASSWORD);
        }

//        redis新增用户登录失败3次，登录失败
//        一.先看该用户是否登录过，没有就给他加个redis数据
        String redisKey = "user:password:error:times"+dto.getUsername();
        String redisData = stringRedisTemplate.opsForValue().get(redisKey);

        redisData = StrUtil.nullToDefault(redisData,"0");
        int errorTimes = Integer.parseInt(redisData);

//        二.判断是否错误3次
        if(errorTimes>=3){
            throw new RuntimeException("密码错误过多，请三小时后再试");
        }



//        2.查到用户比较密码
        String password = dto.getPassword();
        if (!DigestUtil.bcryptCheck(password, user.getPassword())) {
//            三.密码错误一次，redis记录数据增加一次
            stringRedisTemplate.opsForValue().set(redisKey,String.valueOf(++errorTimes),3, TimeUnit.HOURS);

            throw new BaseException(BasicEnum.INCORRECT_PASSWORD);
        }

//        四.登陆成功，redis储存数据失效
        stringRedisTemplate.delete(redisKey);


//        3.查看状态是否正常
        if (StrUtil.equals(user.getDataState(), "1")) {
            throw new BaseException(BasicEnum.ACCOUNT_DISABLED);
        }

//        4.查询用户对应可以访问的资源
        List<String> Paths = resourceMapper.selectListByUserId(user.getId());
//        将集合存入Redis
        stringRedisTemplate.opsForValue().set("user:resource:path:"+user.getId(), JSON.toJSONString(Paths));


//        5.用户名和密码都正确，跳转，返回token，并设置用户ID
        Map<String, Object> map = new HashMap<>();
        map.put("id", user.getId());
        String jwt = JwtUtil.createJWT(jwtTokenProperties.getSecretKey(), jwtTokenProperties.getTtl(), map);
        LoginVo loginVo = BeanUtil.toBean(user, LoginVo.class);
        loginVo.setUserToken(jwt);
        return loginVo;
    }

}
